/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package GISPackage;

import CoalitionCirclePackage.CCPVCoalitionCircleViewerPanel;
import com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;
import java.util.StringTokenizer;
import java.util.Vector;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 *
 * @author rpuckett
 */
public class CCPVBasicGISPanel extends JPanel
{

  /**
   * @return the INFO_COLOR
   */
  public static Color getINFO_COLOR()
  {
    return INFO_COLOR;
  }

  /**
   * @return the NO_INFO_COLOR
   */
  public static Color getNO_INFO_COLOR()
  {
    return NO_INFO_COLOR;
  }

  /**
   * @return the SELECTED_COLOR
   */
  public static Color getSELECTED_COLOR()
  {
    return SELECTED_COLOR;
  }

  /**
   * @return the PRESSED_COLOR
   */
  public static Color getPRESSED_COLOR()
  {
    return PRESSED_COLOR;
  }
  private ArrayList<Point> points = new ArrayList<Point>();
  private ArrayList<ArrayList<Point2D.Double>> GISpoints = new ArrayList<ArrayList<Point2D.Double>>();
  private ArrayList<Line2D.Double> lines = new ArrayList<Line2D.Double>();
  private ArrayList<Polygon> polygons = new ArrayList<Polygon>();
  private HashMap<Integer, Color> polygonColors = new HashMap<Integer, Color>();
  private double xmin = 16.45545000000857;
  private double xmax = 38.0004666854511;
  private double ymin = -46.97892929427326;
  private double ymax = -22.12606999999844;
  private Random randGen = new Random();
  //16.45545000000857 to 38.0004666854511, Y: -46.97892929427326 to -22.12606999999844
  private File mapFile;
  private Point lastMousePoint;
  private Regions regions = new Regions();
  private Vector<Integer> selectedRegionPolygons = new Vector<Integer>();
  private Vector<Region> selectedRegions = new Vector<Region>();
  private String defaultRegionsFilePath = "c:/CCPV Data/regions.txt";
  private static final Color INFO_COLOR = Color.green;
  private static final Color NO_INFO_COLOR = Color.lightGray;
  private static final Color SELECTED_COLOR = Color.orange;
  private static final Color PRESSED_COLOR = Color.yellow;
  private JPopupMenu rightClickOptions = new JPopupMenu();
  private JMenuItem createRegionOption = new JMenuItem("create new region");
  private JMenuItem loadRegionsOption = new JMenuItem("load saved regions");
  private JMenuItem saveRegionsOption = new JMenuItem("save regions");
  private Vector<GISMenuItem> allRegionMenuItems = new Vector<GISMenuItem>();
  // create new region dialog variables
  private Dimension newRegionDialogSize = new Dimension(280, 250);
  private Dimension errorDialogSize = new Dimension(340, 140);
  private File currentRegionStatisticsFile;
  private File currentRegionAltruismFileDirectory;
  private boolean currentRegionStatisticsFileSet = false;
  private boolean currentRegionAltruismFileDirectorySet = false;
  private CCPVBasicGISPanel selfPointer = this;
  // netbeans generated variables
  private javax.swing.JDialog createNewRegionDialog;
  private javax.swing.JButton createNewRegionDialogAltruismButton;
  private javax.swing.JPanel createNewRegionDialogContainer;
  private javax.swing.JTextField createNewRegionDialogName;
  private javax.swing.JLabel createNewRegionDialogNameTitle;
  private javax.swing.JButton createNewRegionDialogStatisticsButton;
  private javax.swing.JLabel createNewRegionDialogTitle;
  private javax.swing.JButton createNewRegionDone;
  private javax.swing.JButton createNewRegionStructuralVariablesButton;
  private javax.swing.JDialog errorDialog;
  private javax.swing.JPanel errorDialogContainer;
  private javax.swing.JTextArea errorDialogText;
  private javax.swing.JFileChooser fileChooser;
  private javax.swing.JScrollPane jScrollPane1;

  public CCPVBasicGISPanel()
  {
    setLayout(null);
    initComponents();
    try
    {
      regions.loadFromFile(new File(defaultRegionsFilePath));
      repaint();
    } catch (IOException e)
    {
      errorDialogText.setText("file reading error: regions could not be loaded.");
      errorDialog.setVisible(true);
      errorDialog.setSize(errorDialogSize);
      errorDialog.setPreferredSize(errorDialogSize);
    }
    setupPopupMenu();
    setupListeners();
    setupDialogListeners();
    setupStartingEnabledStatus();
    setupColors();
    updateUI();
    repaint();
  }

  public CCPVBasicGISPanel(File regionsLoadFile)
  {
    initComponents();
    try
    {
      regions.loadFromFile(regionsLoadFile);
      repaint();
    } catch (IOException e)
    {
      errorDialogText.setText("file reading error: regions could not be loaded.");
      errorDialog.setVisible(true);
      errorDialog.setSize(errorDialogSize);
      errorDialog.setPreferredSize(errorDialogSize);
    }
    setupPopupMenu();
    setupListeners();
    setupDialogListeners();
    setupStartingEnabledStatus();
    setupColors();
    updateUI();
    repaint();
  }

  private void setupStartingEnabledStatus()
  {
    createNewRegionDone.setEnabled(false);
  }

  private void setupDialogListeners()
  {
    createNewRegionDialogAltruismButton.addActionListener(new ActionListener()
    {

      public void actionPerformed(ActionEvent evt)
      {
        getFileChooser().setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        int openVal = getFileChooser().showOpenDialog(getCreateNewRegionDialog());
        if (openVal == JFileChooser.APPROVE_OPTION)
        {
          try
          {
            currentRegionAltruismFileDirectory = getFileChooser().getSelectedFile();
            currentRegionAltruismFileDirectorySet = true;
            if (isCurrentRegionStatisticsFileSet())
            {
              getCreateNewRegionDone().setEnabled(true);
            }
          } catch (Error c)
          {
            System.out.println("ERROR: Loading of data file failed.  Please load another file.");
            getErrorDialogText().setText("Error in loading altruism directory.");
            getErrorDialog().setSize(getErrorDialogSize());
            getErrorDialog().setPreferredSize(getErrorDialogSize());
            getErrorDialog().setVisible(true);
          }
        }
      }
    });

    //createNewRegionDialogName;

    createNewRegionDialogStatisticsButton.addActionListener(new ActionListener()
    {

      public void actionPerformed(ActionEvent evt)
      {
        getFileChooser().setFileSelectionMode(JFileChooser.FILES_ONLY);
        int openVal = getFileChooser().showOpenDialog(getCreateNewRegionDialog());
        if (openVal == JFileChooser.APPROVE_OPTION)
        {
          try
          {
            currentRegionStatisticsFile = getFileChooser().getSelectedFile();
            currentRegionStatisticsFileSet = true;
            if (isCurrentRegionAltruismFileDirectorySet())
            {
              getCreateNewRegionDone().setEnabled(true);
            }
          } catch (Error c)
          {
            System.out.println("ERROR: Loading of data file failed.  Please load another file.");
            getErrorDialogText().setText("Error in loading statistics file.");
            getErrorDialog().setSize(getErrorDialogSize());
            getErrorDialog().setPreferredSize(getErrorDialogSize());
            getErrorDialog().setVisible(true);
          }
        }
      }
    });


    createNewRegionDone.addActionListener(new ActionListener()
    {

      public void actionPerformed(ActionEvent evt)
      {
        if (isCurrentRegionStatisticsFileSet() && isCurrentRegionAltruismFileDirectorySet())
        {
          Color regionColor = new Color(getRandGen().nextInt(255), getRandGen().nextInt(255), getRandGen().nextInt(255));
          String regionName = getCreateNewRegionDialogName().getText();
          getRegions().addRegion(regionName, getSelectedRegionPolygons(), getCurrentRegionStatisticsFile(), getCurrentRegionAltruismFileDirectory(), regionColor);
          selectedRegionPolygons = new Vector<Integer>();
          setupColors();
          getCreateNewRegionDialog().setVisible(false);
          getCreateNewRegionDone().setEnabled(false);
          currentRegionStatisticsFileSet = false;
          currentRegionAltruismFileDirectorySet = false;
        }
      }
    });

  }

  private void setupPopupMenu()
  {
    // setup the layout
    setupMenuOptions();
    rightClickOptions.updateUI();

    // setup the listeners
    createRegionOption.addActionListener(new java.awt.event.ActionListener()
    {

      public void actionPerformed(java.awt.event.ActionEvent evt)
      {
        // activate new region dialog
        getCreateNewRegionDialog().setVisible(true);
        getCreateNewRegionDialog().setSize(getNewRegionDialogSize());
        getCreateNewRegionDialog().setPreferredSize(getNewRegionDialogSize());
      }
    });

    saveRegionsOption.addActionListener(new java.awt.event.ActionListener()
    {

      public void actionPerformed(java.awt.event.ActionEvent evt)
      {
        getFileChooser().setFileSelectionMode(JFileChooser.FILES_ONLY);
        int saveVal = getFileChooser().showSaveDialog(null);
        if (saveVal == JFileChooser.APPROVE_OPTION)
        {
          File regionsSaveFile = getFileChooser().getSelectedFile();
          try
          {
            getRegions().saveToFile(regionsSaveFile);
          } catch (Error c)
          {
            System.out.println("ERROR: Loading of data file failed.  Please load another file.");
            getErrorDialog().setSize(getErrorDialogSize());
            getErrorDialog().setPreferredSize(getErrorDialogSize());
            getErrorDialog().setVisible(true);
          }
        }
      }
    });

    loadRegionsOption.addActionListener(new java.awt.event.ActionListener()
    {

      public void actionPerformed(java.awt.event.ActionEvent evt)
      {
        getFileChooser().setFileSelectionMode(JFileChooser.FILES_ONLY);
        int openVal = getFileChooser().showOpenDialog(null);
        if (openVal == JFileChooser.APPROVE_OPTION)
        {
          File regionsLoadFile = getFileChooser().getSelectedFile();
          try
          {
            getRegions().loadFromFile(regionsLoadFile);
            setupColors();
          } catch (IOException c)
          {
            System.out.println("ERROR: Loading of data file failed.  Please load another file.");
            getErrorDialog().setSize(getErrorDialogSize());
            getErrorDialog().setPreferredSize(getErrorDialogSize());
            getErrorDialog().setVisible(true);
          }
        }
      }
    });
  }

  private void setupMenuOptions()
  {
    rightClickOptions.removeAll();
    rightClickOptions.add(createRegionOption);
    rightClickOptions.add(saveRegionsOption);
    rightClickOptions.add(loadRegionsOption);

    // create a new option for each selected region
    Vector<GISMenuItem> selectedRegionsMenuItems = setupSelectedRegionsMenuItems();
    for (GISMenuItem regionItem : selectedRegionsMenuItems)
    {
      rightClickOptions.add(regionItem);
      rightClickOptions.updateUI();
      repaintAll();
    }
  }

  private Vector<GISMenuItem> setupSelectedRegionsMenuItems()
  {
    Vector<GISMenuItem> ret = new Vector<GISMenuItem>();

    for (final Region r : selectedRegions)
    {
      boolean rItemFound = false;
      for (GISMenuItem g : allRegionMenuItems)
      {
        if (g.region.equals(r))
        {
          ret.add(g);
          rItemFound = true;
          break;
        }
      }
      if (!rItemFound)// we need to make a new item
      {
        GISMenuItem regionItem = new GISMenuItem("run simulation for " + r.name, r);

        regionItem.addActionListener(new java.awt.event.ActionListener()
        {

          public void actionPerformed(java.awt.event.ActionEvent evt)
          {
            // load data into viewer!!!!!!!!!!!!!!!!!!!!!!!!!
            //dfd

            Dimension panelD = new Dimension(1000, 700);
            JDialog coalitionCircleViewerDialog = new JDialog();
            coalitionCircleViewerDialog.setLayout(null);
            CCPVCoalitionCircleViewerPanel viewer = new CCPVCoalitionCircleViewerPanel("c:/CCPV Data/tests/indoformat.txt");
            viewer.setSize(panelD);
            viewer.setPreferredSize(panelD);
            coalitionCircleViewerDialog.add(viewer);
            coalitionCircleViewerDialog.setSize(panelD);
            coalitionCircleViewerDialog.setPreferredSize(panelD);
            coalitionCircleViewerDialog.setVisible(true);

          }
        });

        regionItem.addMouseListener(new java.awt.event.MouseAdapter()
        {

          public void mouseEntered(java.awt.event.MouseEvent evt)
          {
            getSelectedRegions().clear();
            getSelectedRegions().add(r);
            setupColors();
          }

          public void mouseExited(java.awt.event.MouseEvent evt)
          {
            getSelectedRegions().remove(r);
            setupColors();
          }
        });

        ret.add(regionItem);
        allRegionMenuItems.add(regionItem);
      }
    }

    return ret;
  }

  private void initComponents()
  {
    createNewRegionDialog = new javax.swing.JDialog();
    createNewRegionDialogContainer = new javax.swing.JPanel();
    createNewRegionDialogTitle = new javax.swing.JLabel();
    createNewRegionDialogName = new javax.swing.JTextField();
    createNewRegionDialogNameTitle = new javax.swing.JLabel();
    createNewRegionDialogStatisticsButton = new javax.swing.JButton();
    createNewRegionDialogAltruismButton = new javax.swing.JButton();
    createNewRegionDone = new javax.swing.JButton();
    createNewRegionStructuralVariablesButton = new javax.swing.JButton();
    fileChooser = new javax.swing.JFileChooser();
    errorDialog = new javax.swing.JDialog();
    errorDialogContainer = new javax.swing.JPanel();
    jScrollPane1 = new javax.swing.JScrollPane();
    errorDialogText = new javax.swing.JTextArea();

    createNewRegionDialogContainer.setBackground(new java.awt.Color(204, 255, 255));
    createNewRegionDialogContainer.setLayout(null);

    createNewRegionDialogTitle.setFont(new java.awt.Font("Tahoma", 3, 14));
    createNewRegionDialogTitle.setText("Create a new region");
    createNewRegionDialogContainer.add(createNewRegionDialogTitle);
    createNewRegionDialogTitle.setBounds(10, 10, 200, 17);

    createNewRegionDialogContainer.add(createNewRegionDialogName);
    createNewRegionDialogName.setBounds(10, 60, 240, 20);

    createNewRegionDialogNameTitle.setText("Name");
    createNewRegionDialogContainer.add(createNewRegionDialogNameTitle);
    createNewRegionDialogNameTitle.setBounds(10, 40, 120, 14);

    createNewRegionDialogStatisticsButton.setText("Set statistics file");
    createNewRegionDialogContainer.add(createNewRegionDialogStatisticsButton);
    createNewRegionDialogStatisticsButton.setBounds(10, 90, 240, 23);

    createNewRegionDialogAltruismButton.setText("Set altruism file directory");

    createNewRegionDialogContainer.add(createNewRegionDialogAltruismButton);
    createNewRegionDialogAltruismButton.setBounds(10, 120, 240, 23);

    createNewRegionDone.setText("Done");
    createNewRegionDialogContainer.add(createNewRegionDone);
    createNewRegionDone.setBounds(10, 180, 240, 23);

    createNewRegionStructuralVariablesButton.setText("Set structural variables file");
    createNewRegionDialogContainer.add(createNewRegionStructuralVariablesButton);
    createNewRegionStructuralVariablesButton.setBounds(10, 150, 240, 23);

    javax.swing.GroupLayout createNewRegionDialogLayout = new javax.swing.GroupLayout(createNewRegionDialog.getContentPane());
    createNewRegionDialog.getContentPane().setLayout(createNewRegionDialogLayout);
    createNewRegionDialogLayout.setHorizontalGroup(
            createNewRegionDialogLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addComponent(createNewRegionDialogContainer, javax.swing.GroupLayout.PREFERRED_SIZE, 265, javax.swing.GroupLayout.PREFERRED_SIZE));
    createNewRegionDialogLayout.setVerticalGroup(
            createNewRegionDialogLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addComponent(createNewRegionDialogContainer, javax.swing.GroupLayout.DEFAULT_SIZE, 219, Short.MAX_VALUE));

    errorDialogContainer.setBackground(new java.awt.Color(255, 204, 204));

    errorDialogText.setBackground(new java.awt.Color(255, 204, 204));
    errorDialogText.setColumns(20);
    errorDialogText.setRows(5);
    jScrollPane1.setViewportView(errorDialogText);

    javax.swing.GroupLayout errorDialogContainerLayout = new javax.swing.GroupLayout(errorDialogContainer);
    errorDialogContainer.setLayout(errorDialogContainerLayout);
    errorDialogContainerLayout.setHorizontalGroup(
            errorDialogContainerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(errorDialogContainerLayout.createSequentialGroup().addContainerGap().addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 306, Short.MAX_VALUE).addContainerGap()));
    errorDialogContainerLayout.setVerticalGroup(
            errorDialogContainerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(errorDialogContainerLayout.createSequentialGroup().addContainerGap().addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE).addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)));

    javax.swing.GroupLayout errorDialogLayout = new javax.swing.GroupLayout(errorDialog.getContentPane());
    errorDialog.getContentPane().setLayout(errorDialogLayout);
    errorDialogLayout.setHorizontalGroup(
            errorDialogLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addComponent(errorDialogContainer, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE));
    errorDialogLayout.setVerticalGroup(
            errorDialogLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addComponent(errorDialogContainer, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE));

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
    this.setLayout(layout);
    layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 0, Short.MAX_VALUE));
    layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 0, Short.MAX_VALUE));
  }

  // zooms according to the percentage
  public void zoom(double percentage)
  {
    int newWidth = (int) (getWidth() * percentage);
    int newHeight = (int) (getHeight() * percentage);
    Dimension newD = new Dimension(newWidth, newHeight);
    setSize(newD);
    setPreferredSize(newD);
    loadFromFile();
    setupColors();
    repaintAll();
  }

  private void setupListeners()
  {


    addMouseWheelListener(new java.awt.event.MouseWheelListener()
    {

      public void mouseWheelMoved(java.awt.event.MouseWheelEvent evt)
      {
        int wheelRotation = evt.getWheelRotation();

        if (wheelRotation < 0)
        {
          zoom(1.1);
        }
        else
        {
          zoom(0.9);
        }
      }
    });

    addMouseListener(new java.awt.event.MouseAdapter()
    {

      public void mouseClicked(java.awt.event.MouseEvent evt)
      {
        Point clickP = evt.getPoint();

        // search through the polygons to see which is clicked...
        Polygon clickedPoly = null;
        int clickedIndex = 0;
        int i = 0;
        for (Polygon p : getPolygons())
        {
          if (p.contains(clickP))
          {
            clickedIndex = i;
            clickedPoly = p;
            break;
          }
          i++;
        }

        // testing printing selected region
        String selectedString = "";
        for (int j = 0; j < getSelectedRegionPolygons().size(); j++)
        {
          selectedString += getSelectedRegionPolygons().get(j) + " * ";
        }
        System.out.println(selectedString);

        if (evt.isShiftDown())
        {
          getSelectedRegionPolygons().add(clickedIndex);
        }
        else if (!(evt.getButton() == MouseEvent.BUTTON3))
        {
          getSelectedRegionPolygons().clear();
        }

        setupColors();

        // show options if it's a right click
        if (evt.getButton() != MouseEvent.BUTTON1)
        {
          System.out.println("click");
          Point evtP = evt.getPoint();
          getRightClickOptions().show(evt.getComponent(), evtP.x, evtP.y);
          // setup menu options for all selected regions
          // first we must make sure we set the selected regions
          getSelectedRegions().clear();
          selectedRegions = getPolygonRegions(clickedIndex);
          System.out.println("selected regions size: " + getSelectedRegions().size());
          setupMenuOptions();
        }
        else
        {
          getSelectedRegions().clear();
        }

        for (int j = 0; j < getSelectedRegionPolygons().size(); j++)
        {
          System.out.println(getSelectedRegionPolygons().get(j));
        }
      }

      public void mouseEntered(java.awt.event.MouseEvent evt)
      {
      }

      public void mouseExited(java.awt.event.MouseEvent evt)
      {
      }

      public void mousePressed(java.awt.event.MouseEvent evt)
      {
        Point clickP = evt.getPoint();

        // search through the polygons to see which is clicked...
        int i = 0;
        for (Polygon p : getPolygons())
        {
          if (p.contains(clickP))
          {
            Vector<Region> pRegions = getPolygonRegions(i);
            if (pRegions.size() > 0 && !evt.isShiftDown()) // if p belongs to a region already and the user isn't selecting a new region
            {
              for (Region r : pRegions)
              {
                Vector<Integer> v = r.polygons;
                Color regionColor = getRegions().getRegionColor(v);
                for (Integer vi : v)
                {
                  getPolygonColors().put(vi, lightenColor(regionColor));
                }
              }
            }
            else // if p isn't in a region
            {
              getPolygonColors().put(i, getSELECTED_COLOR());
            }
          }
          lastMousePoint = evt.getLocationOnScreen();
          i++;
        }

        repaintAll();
      }

      public void mouseReleased(java.awt.event.MouseEvent evt)
      {
        setupColors();
      }
    });
    addMouseMotionListener(new java.awt.event.MouseMotionAdapter()
    {

      public void mouseDragged(java.awt.event.MouseEvent evt)
      {
        Point evtP = evt.getLocationOnScreen();
        int xDiff = evtP.x - getLastMousePoint().x;
        int yDiff = evtP.y - getLastMousePoint().y;
        Point currentL = getLocation();

        Point newP = new Point(currentL.x + xDiff, currentL.y + yDiff);

        setLocation(newP);
        lastMousePoint = evtP;
      }

      public void mouseMoved(java.awt.event.MouseEvent evt)
      {
      }
    });
  }

  private void setupColors()
  {
    for (int i = 0; i < polygons.size(); i++)
    {
      boolean polygonColorSet = false;

      if (selectedRegionPolygons.contains(i))
      {
        polygonColors.put(i, SELECTED_COLOR);
        polygonColorSet = true;
      }

      if ((selectedRegions.size() == 1) && !polygonColorSet)// if there's only 1 selected region
      {
        Region r = selectedRegions.get(0);
        // check if this region contains i
        if (r.polygons.contains(i))
        {
          polygonColors.put(i, SELECTED_COLOR);
          polygonColorSet = true;
        }
      }

      if (polygonIsInRegion(i) && !polygonColorSet)
      {
        Vector<Region> pRegions = getPolygonRegions(i);
        int newRed = 0;
        int newGreen = 0;
        int newBlue = 0;

        for (Region r : pRegions)
        {
          Color c = r.regionColor;
          newRed += c.getRed();
          newGreen += c.getGreen();
          newBlue += c.getBlue();
        }
        if (newRed > 255)
        {
          newRed = 255;
        }
        if (newGreen > 255)
        {
          newGreen = 255;
        }
        if (newBlue > 255)
        {
          newBlue = 255;
        }

        Color pColor = new Color(newRed, newGreen, newBlue);

        polygonColors.put(i, pColor);
        polygonColorSet = true;
      }

      if (!polygonColorSet)
      {
        polygonColors.put(i, NO_INFO_COLOR);
      }
    }
    repaintAll();
  }

  private Color lightenColor(Color c)
  {
    int red = c.getRed() + 30;
    int green = c.getGreen() + 30;
    int blue = c.getBlue() + 30;

    if (red > 255)
    {
      red = 255;
    }
    if (green > 255)
    {
      green = 255;
    }
    if (blue > 255)
    {
      blue = 255;
    }

    return new Color(red, green, blue);
  }

  private boolean polygonIsInRegion(int pIndex)
  {
    for (Region r : regions.regions)
    {
      if (r.containsIndex(pIndex))
      {
        return true;
      }
    }

    return false;
  }

  // returns all regions containing pIndex
  private Vector<Region> getPolygonRegions(int pIndex)
  {
    Vector<Region> ret = new Vector<Region>();

    for (Region r : regions.regions)
    {
      if (r.containsIndex(pIndex))
      {
        ret.add(r);
      }
    }

    return ret;
  }

  // returns all regions with containing the point
  public Vector<Region> getRegionInfoForMouseClick(Point p)
  {
    // first find the index of the polygon containing the mouse event
    int index = 0;
    for (int i = 0; i < polygons.size(); i++)
    {
      if (polygons.get(i).contains(p))
      {
        index = i;
      }
    }

    return getPolygonRegions(index);
  }

  public ArrayList<Polygon> getPolygons()
  {
    return polygons;
  }

  public void setPolygons(ArrayList<Polygon> polygons)
  {
    this.polygons = polygons;
  }

  public void setScale(double xmin, double xmax, double ymin, double ymax)
  {
    this.xmin = xmin;
    this.xmax = xmax;
    this.ymin = ymin;
    this.ymax = ymax;
  }

  public void addPointDirect(Point2D.Double point)
  {
    points.add(new Point((int) (point.x), (int) (point.y)));
    repaintAll();
  }

  public void addPoint(Point2D.Double point)
  {
    points.add(new Point(scale(point.x, true), this.getSize().height - scale(point.y, false)));
  }

  public void addLine(Line2D.Double line)
  {
    lines.add(new Line2D.Double(scale(line.x1, true), scale(line.y1, false), scale(line.x2, true), scale(line.y2, false)));
  }

  public void clearAll()
  {
    GISpoints.clear();
    points.clear();
    lines.clear();
    polygons.clear();
    repaintAll();
  }

  private int scale(double value, boolean isX)
  {

    double magicx = 1;// 1.29
    double magicy = 1;// 1.95
    int value2;
    if (isX)
    {
      value2 = (int) (((value - xmin) / (Math.abs(xmax - xmin))) * this.getWidth() * magicx); // 1.29
    }
    else
    {
      value2 = (int) (this.getHeight() * magicy - (((value - ymin) / (Math.abs(ymax - ymin))) * this.getHeight() * magicy));
    }
    if (value2 < 0)
    {
      return 0;
    }
    //System.out.println(value + "->" + value2 + "  " + isX);

    return value2;
  }

  public void addGISpoints(ArrayList<Point2D.Double> points)
  {
    GISpoints.add(points);
  }

  public void buildPolygons()
  {
    Polygon poly;
    int i = 0;
    for (ArrayList<Point2D.Double> pts : GISpoints)
    {
      poly = new Polygon();
      double xval, yval;
      for (Point2D point : pts)
      {
        xval = scale(point.getX(), true);
        yval = scale(point.getY(), false);
        poly.addPoint((int) xval, (int) yval);
      }
      polygons.add(poly);
      //Color newColor = new Color(randGen.nextInt(255), randGen.nextInt(255), randGen.nextInt(255));
      Color newColor = Color.lightGray;
      polygonColors.put(i, newColor);
      i++;
    }
  }

  public void clearGIS()
  {
    GISpoints.clear();
  }

  public void readXmlFile(String path)
  {
    mapFile = new File(path);
    loadFromFile();
  }

  private void loadFromFile()
  {
    DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder docBuilder;
    Document doc;
    double readXMin = 500, readYMin = 500, readXMax = -500, readYMax = -500;
    clearAll();
    try
    {
      docBuilder = docBuilderFactory.newDocumentBuilder();
      doc = docBuilder.parse(mapFile);

      doc.getDocumentElement().normalize();
      String root = doc.getDocumentElement().getNodeName();
      //System.out.println("Processing file: " + path + " with root: " + root + "\n");


      NodeList listOfPolygons = doc.getElementsByTagName("LinearRing");

      ArrayList<Point2D.Double> readPoints;
      for (int i = 0; i < listOfPolygons.getLength(); i++)
      {
        readPoints = new ArrayList<Point2D.Double>();

        Node polygon = listOfPolygons.item(i);

        NodeList children = polygon.getChildNodes();
        for (int j = 0; j < children.getLength(); j++)
        {
          if (children.item(j).getNodeName().equals("coordinates"))
          {
            StringTokenizer st1 = new StringTokenizer(children.item(j).getTextContent());
            StringTokenizer st2;
            int count = 0;
            String token;
            String[] fields;
            Point2D.Double point;
            while (st1.hasMoreTokens())
            {
              count++;
              token = st1.nextToken();
              fields = token.split(",");
              point = new Point2D.Double(Double.parseDouble(fields[0]), Double.parseDouble(fields[1]));
              readPoints.add(point);
              //    System.out.println(point);
              if (point.x > readXMax)
              {
                readXMax = point.x;
              }
              if (point.x < readXMin)
              {
                readXMin = point.x;
              }
              if (point.y > readYMax)
              {
                readYMax = point.y;
              }
              if (point.y < readYMin)
              {
                readYMin = point.y;
              }
            }
            addGISpoints(readPoints);
          }
        }
      }


    } catch (MalformedByteSequenceException e)
    {
      System.out.println("Bad XML file : " + e.getMessage());
    } catch (FileNotFoundException e)
    {
      System.out.println("File not found : " + e.getMessage());
    } catch (IOException e)
    {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (SAXException e)
    {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (ParserConfigurationException e)
    {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    setScale(readXMin, readXMax, readYMin, readYMax);
    buildPolygons();
  //System.out.println("Done with xml");

  //System.out.println("X: " + readXMin + " to " + readXMax + ", Y: " + readYMin + " to " + readYMax);
  }

  @Override
  public void paintComponent(Graphics g)
  {
    //   super.paintComponent(g);    // paints background
    g.setColor(Color.white);
    g.fillRect(0, 0, this.getWidth(), this.getHeight());
    g.setColor(Color.BLACK);
    //g.drawLine(0,0,0,this.getHeight());
    //g.drawLine(0,0,this.getWidth(),0);
    //g.drawLine(this.getWidth(),0,this.getWidth(),this.getHeight());
    //g.drawLine(0,this.getHeight(),this.getWidth(),this.getHeight());

    for (Line2D.Double line : lines)
    {
      g.drawLine((int) line.x1, (int) line.y1, (int) line.x2, (int) line.y2);

    }

    for (int i = 0; i < polygons.size(); i++)
    {

      Polygon poly = polygons.get(i);
      //g.setColor(new Color(r.nextInt(256), r.nextInt(256), r.nextInt(256)));
      g.setColor(polygonColors.get(i));
      g.fillPolygon(poly);
      g.setColor(Color.BLACK);
      g.drawPolygon(poly);
    }

    for (Point point : points)
    {
      g.setColor(new Color(randGen.nextInt(256), randGen.nextInt(256), randGen.nextInt(256)));
      g.fillOval(point.x, point.y, 2, 2);
      g.setColor(Color.BLACK);
      g.drawOval(point.x, point.y, 2, 2);

    }

  //    System.out.println(scale(16.45545000000857,true)+ " " + scale( -46.97892929427326,false));
  //16.45545000000857 to 38.0004666854511, Y: -46.97892929427326 to -22.12606999999844

  //  System.out.println(scale(38.0004666854511,true)+ " " + scale(-22.12606999999844,false));

  }

  public void repaintAll()
  {
    if (this.getParent() != null)
    {
      this.getParent().repaint();
    }
    else
    {
      repaint();
    }
  }

  /**
   * @return the points
   */
  public ArrayList<Point> getPoints()
  {
    return points;
  }

  /**
   * @return the GISpoints
   */
  public ArrayList<ArrayList<Point2D.Double>> getGISpoints()
  {
    return GISpoints;
  }

  /**
   * @return the lines
   */
  public ArrayList<Line2D.Double> getLines()
  {
    return lines;
  }

  /**
   * @return the polygonColors
   */
  public HashMap<Integer, Color> getPolygonColors()
  {
    return polygonColors;
  }

  /**
   * @return the xmin
   */
  public double getXmin()
  {
    return xmin;
  }

  /**
   * @return the xmax
   */
  public double getXmax()
  {
    return xmax;
  }

  /**
   * @return the ymin
   */
  public double getYmin()
  {
    return ymin;
  }

  /**
   * @return the ymax
   */
  public double getYmax()
  {
    return ymax;
  }

  /**
   * @return the randGen
   */
  public Random getRandGen()
  {
    return randGen;
  }

  /**
   * @return the mapFile
   */
  public File getMapFile()
  {
    return mapFile;
  }

  /**
   * @return the lastMousePoint
   */
  public Point getLastMousePoint()
  {
    return lastMousePoint;
  }

  /**
   * @return the regions
   */
  public Regions getRegions()
  {
    return regions;
  }

  /**
   * @return the selectedRegion
   */
  public Vector<Integer> getSelectedRegionPolygons()
  {
    return selectedRegionPolygons;
  }

  /**
   * @return the defaultRegionsFilePath
   */
  public String getDefaultRegionsFilePath()
  {
    return defaultRegionsFilePath;
  }

  /**
   * @return the rightClickOptions
   */
  public JPopupMenu getRightClickOptions()
  {
    return rightClickOptions;
  }

  /**
   * @return the createRegionOption
   */
  public JMenuItem getCreateRegionOption()
  {
    return createRegionOption;
  }

  /**
   * @return the loadRegionsOption
   */
  public JMenuItem getLoadRegionsOption()
  {
    return loadRegionsOption;
  }

  /**
   * @return the saveRegionsOption
   */
  public JMenuItem getSaveRegionsOption()
  {
    return saveRegionsOption;
  }

  /**
   * @return the newRegionDialogSize
   */
  public Dimension getNewRegionDialogSize()
  {
    return newRegionDialogSize;
  }

  /**
   * @return the errorDialogSize
   */
  public Dimension getErrorDialogSize()
  {
    return errorDialogSize;
  }

  /**
   * @return the currentRegionStatisticsFile
   */
  public File getCurrentRegionStatisticsFile()
  {
    return currentRegionStatisticsFile;
  }

  /**
   * @return the currentRegionAltruismFileDirectory
   */
  public File getCurrentRegionAltruismFileDirectory()
  {
    return currentRegionAltruismFileDirectory;
  }

  /**
   * @return the currentRegionStatisticsFileSet
   */
  public boolean isCurrentRegionStatisticsFileSet()
  {
    return currentRegionStatisticsFileSet;
  }

  /**
   * @return the currentRegionAltruismFileDirectorySet
   */
  public boolean isCurrentRegionAltruismFileDirectorySet()
  {
    return currentRegionAltruismFileDirectorySet;
  }

  /**
   * @return the selfPointer
   */
  public CCPVBasicGISPanel getSelfPointer()
  {
    return selfPointer;
  }

  /**
   * @return the createNewRegionDialog
   */
  public javax.swing.JDialog getCreateNewRegionDialog()
  {
    return createNewRegionDialog;
  }

  /**
   * @return the createNewRegionDialogAltruismButton
   */
  public javax.swing.JButton getCreateNewRegionDialogAltruismButton()
  {
    return createNewRegionDialogAltruismButton;
  }

  /**
   * @return the createNewRegionDialogContainer
   */
  public javax.swing.JPanel getCreateNewRegionDialogContainer()
  {
    return createNewRegionDialogContainer;
  }

  /**
   * @return the createNewRegionDialogName
   */
  public javax.swing.JTextField getCreateNewRegionDialogName()
  {
    return createNewRegionDialogName;
  }

  /**
   * @return the createNewRegionDialogNameTitle
   */
  public javax.swing.JLabel getCreateNewRegionDialogNameTitle()
  {
    return createNewRegionDialogNameTitle;
  }

  /**
   * @return the createNewRegionDialogStatisticsButton
   */
  public javax.swing.JButton getCreateNewRegionDialogStatisticsButton()
  {
    return createNewRegionDialogStatisticsButton;
  }

  /**
   * @return the createNewRegionDialogTitle
   */
  public javax.swing.JLabel getCreateNewRegionDialogTitle()
  {
    return createNewRegionDialogTitle;
  }

  /**
   * @return the createNewRegionDone
   */
  public javax.swing.JButton getCreateNewRegionDone()
  {
    return createNewRegionDone;
  }

  /**
   * @return the errorDialog
   */
  public javax.swing.JDialog getErrorDialog()
  {
    return errorDialog;
  }

  /**
   * @return the errorDialogContainer
   */
  public javax.swing.JPanel getErrorDialogContainer()
  {
    return errorDialogContainer;
  }

  /**
   * @return the errorDialogText
   */
  public javax.swing.JTextArea getErrorDialogText()
  {
    return errorDialogText;
  }

  /**
   * @return the fileChooser
   */
  public javax.swing.JFileChooser getFileChooser()
  {
    return fileChooser;
  }

  /**
   * @return the jScrollPane1
   */
  public javax.swing.JScrollPane getJScrollPane1()
  {
    return jScrollPane1;
  }

  /**
   * @return the selectedRegions
   */
  public Vector<Region> getSelectedRegions()
  {
    return selectedRegions;
  }

  /**
   * @return the createNewRegionStructuralVariablesButton
   */
  public javax.swing.JButton getCreateNewRegionStructuralVariablesButton()
  {
    return createNewRegionStructuralVariablesButton;
  }

  /**
   * @return the allRegionMenuItems
   */
  public Vector<GISMenuItem> getAllRegionMenuItems()
  {
    return allRegionMenuItems;
  }
}
